package com.hp.common.access;

import com.hp.common.access.model.SysAccessModel;
import com.hp.common.tool.StringTool;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.Authorization;
import io.swagger.annotations.AuthorizationScope;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 控制类权限处理类（主要将注释转成权限资源模型）
 * @author mcfan
 */
@Component
public class AccessInitProcessor implements BeanPostProcessor {

    /**
     * 权限集合
     */
    private List<SysAccessModel> accessList = new ArrayList<>();
    /**
     * 模块权限
     */
    private Map<String,SysAccessModel> moduleMap = new HashMap<>();
    /**
     * 权限标识正则
     */
    private final static String ACCESS_REGEX = "(^_([a-zA-Z0-9:]_?)*$)|(^[a-zA-Z:](_?[a-zA-Z0-9:])*_?$)";

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
       if(beanName.endsWith("Controller")){
           Api api = bean.getClass().getAnnotation(Api.class);
           if(api==null){
               return bean;
           }
           Authorization[] authorizations = api.authorizations();;
           if(authorizations.length>0){
               Authorization authorization = authorizations[0];
               //处理模块
               SysAccessModel moduleAccess = moduleMap.get(authorization.value());
               if(null == moduleAccess){
                   moduleAccess = handleAuthorization(authorization);
                   moduleAccess.setChildren(new ArrayList<>());
                   if(StringTool.isNotEmpty(moduleAccess.getAccess())){
                       accessList.add(moduleAccess);
                       moduleMap.put(authorization.value(),moduleAccess);
                   }
               }

               //处理控制类
               AuthorizationScope[] authorizationScopes = authorization.scopes();
               if (authorizations.length > 0){
                   AuthorizationScope authorizationScope = authorizationScopes[0];
                   SysAccessModel controllerAccess = handleAuthorizationScope(authorizationScope);
                   controllerAccess.setChildren(new ArrayList<>());
                   if (StringTool.isNotEmpty(controllerAccess.getAccess())){
                       moduleAccess.getChildren().add(controllerAccess);
                   }

                   //处理方法
                   Method[] methods = bean.getClass().getMethods();
                   for (Method method : methods) {
                       ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
                       if (apiOperation==null){
                           continue;
                       }
                       authorizations = apiOperation.authorizations();
                       if(authorizations.length>0){
                           authorization = authorizations[0];
                           authorizationScopes = authorization.scopes();
                           if(authorizations.length>0){
                               authorizationScope = authorizationScopes[0];
                               SysAccessModel methodAccess = handleAuthorizationScope(authorizationScope);
                               if (StringTool.isNotEmpty(methodAccess.getAccess())){
                                   controllerAccess.getChildren().add(methodAccess);
                               }else {
                                   String value = apiOperation.value();
                                   String notes = apiOperation.notes();
                                   if(notes.matches(ACCESS_REGEX)){
                                       SysAccessModel accessModel = new SysAccessModel();
                                       accessModel.setId(notes);
                                       accessModel.setAccess(notes);
                                       accessModel.setUri("/"+notes.replaceAll(":","/"));
                                       accessModel.setName(value);
                                       accessModel.setRemark(value);
                                       controllerAccess.getChildren().add(accessModel);
                                   }
                               }
                           }
                       }
                   }
               }
           }
       }
        return bean;
    }


    /**
     * 处理权限模块
     * @param authorization
     * @return
     */
    private SysAccessModel handleAuthorization(Authorization authorization) {
        SysAccessModel moduleAccess = new SysAccessModel();
        String value = authorization.value();
        String arr [] = value.split("\\|");
        if (arr.length==2){
            moduleAccess.setId(arr[0]);
            moduleAccess.setAccess(arr[0]);
            moduleAccess.setName(arr[1]);
            moduleAccess.setRemark(arr[1]);
        }else{
            moduleAccess.setId(value);
            moduleAccess.setAccess(value);
            moduleAccess.setName(value);
            moduleAccess.setRemark(value);
        }
        moduleAccess.setUri("/"+moduleAccess.getAccess().replaceAll(":","/"));
        return moduleAccess;
    }

    /**
     * 处理控制类
     * @param authorizationScope
     * @return
     */
    private SysAccessModel handleAuthorizationScope(AuthorizationScope authorizationScope) {
        SysAccessModel access = new SysAccessModel();
        String scope = authorizationScope.scope();
        String description = authorizationScope.description();
        access.setId(scope);
        access.setAccess(scope);
        access.setUri("/"+scope.replaceAll(":","/"));
        access.setName(description);
        access.setRemark(description);
        return access;
    }

    public List<SysAccessModel> getAccessList(){
        return  accessList;
    }

    /**
     * 获取apiOperation获取权限标识
     * @param apiOperation
     * @return
     */
    public static String getAccess(ApiOperation apiOperation){
        if (apiOperation==null){
            return null;
        }
        Authorization[] authorizations = apiOperation.authorizations();
        if (authorizations.length == 0){
            return null;
        }
        AuthorizationScope[] authorizationScopes = authorizations[0].scopes();
        if (authorizationScopes.length == 0){
            return null;
        }
        String access = authorizationScopes[0].scope();
        if (StringTool.isEmpty(access)){
            String notes = apiOperation.notes();
            if (notes.matches(ACCESS_REGEX)){
                access = notes;
            }
        }
        return access;
    }
}
